package org.x.usermod.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.x.commonmod.config.InsufficientPermissionsException;
import org.x.usermod.dto.AchieveSmsDTO;
import org.x.usermod.dto.LawyerRegisterDTO;
import org.x.usermod.dto.pubRegisterDTO;
import org.x.usermod.entity.SysUser;
import org.x.usermod.entity.LawyerEntity;
import org.x.usermod.mapper.LawyersMapper;
import org.x.usermod.mapper.RegisterMapper;
import org.x.usermod.service.RegisterService;
import org.x.usermod.vo.lawyerRegisterVO;
import org.x.usermod.vo.pubRegisterVO;

import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

@Slf4j
@Service
public class RegisterServiceImpl extends ServiceImpl<RegisterMapper,SysUser> implements RegisterService  {

    @Autowired
    private RegisterMapper registerMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private LawyersMapper lawyersMapper;

    /**
     * 获取短信验证码（纯数字）
     * @param achieveSmsDTO
     * @return
     */
    @Override
    public String achieveSms(AchieveSmsDTO achieveSmsDTO) {
        Random random = new Random();
        Long code= 100000+random.nextLong(900000);
        String codeStr = code.toString();
        redisTemplate.opsForValue().set(
                "sms_code:" + achieveSmsDTO.getMobile(),
                codeStr,
                5,
                java.util.concurrent.TimeUnit.MINUTES
        );
        log.info("短信验证码为：{}",codeStr);
        return codeStr;
    }

    /**
     * 公众注册接口业务
     * @param pubRegisterDTO
     * @return
     */
    @Override
    public pubRegisterVO pubRegister( pubRegisterDTO pubRegisterDTO) {
        //拿到用户传递的验证码和电话号码
        String smsCode = pubRegisterDTO.getSmsCode();
        String mobile = pubRegisterDTO.getMobile();
        //从redis中获取存储的验证码
        String code = (String) redisTemplate.opsForValue().get("sms_code:" + mobile);
        //校验验证码
        if(code == null){
            throw new RuntimeException("验证码不存在");
        }
        if(!code.equals(smsCode)){
            throw new RuntimeException("验证码错误");
        }
        //数据加工
        SysUser User = new SysUser();
        //密码加密sha256
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            byte[] hash = messageDigest.digest(pubRegisterDTO.getPassword().getBytes());
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            User.setPassword(hexString.toString());
        } catch (Exception e) {
            throw new RuntimeException("密码加密失败");
        }
        User.setUserType("USER");
        //用uuid创建随机的用户名@TODO
        User.setUsername(UUID.randomUUID().toString());
        //设置手机号
        User.setMobile(mobile);
        //设置创建时间和更新时间
        User.setCreatedTime(new Date());
        User.setUpdatedTime(new Date());
        //创建用户，空的值不插入
        try{
            registerMapper.insertSelective(User);
        }catch (Exception e){
            throw new RuntimeException("手机号已被注册");
        }
        //返回用户信息
        pubRegisterVO pubRegisterVO = new pubRegisterVO();
        SysUser sysUser = registerMapper.selectOneByMap(Map.of("mobile", pubRegisterDTO.getMobile()));
        pubRegisterVO.setUserId(sysUser.getId());
        pubRegisterVO.setToken(StpUtil.getTokenValue());
        //清除redis缓存
        redisTemplate.delete("sms_code:" + mobile);
        return pubRegisterVO;
    }

    /**
     * 律师注册接口业务
     * @param lawyerRegisterDTO
     * @return
     */
    @Override
    public lawyerRegisterVO lawyerRegister(LawyerRegisterDTO lawyerRegisterDTO) {
        //@TODO 根据身份证照片实现自动读取填充证件信息
        LawyerEntity lawyerEntity = new LawyerEntity();
        BeanUtils.copyProperties(lawyerRegisterDTO,lawyerEntity);
        //设置状态为PENDING
        lawyerEntity.setStatus("AVAILABLE");
        lawyerRegisterVO lawyerRegisterVO = new lawyerRegisterVO();
        //用uuid生成审核id
        lawyerRegisterVO.setAuditId(UUID.randomUUID().toString());
        //设置估计时间为当前时间延后三天
        lawyerRegisterVO.setEstimateTime(LocalDateTime.now().plusDays(3));
        // @TODO插入数据库，用户表和律师表
        SysUser user=new SysUser();
        user.setUserType("LAWYER");
        BeanUtils.copyProperties(lawyerRegisterDTO,user);
        //用uuid创建随机的用户名
        user.setUsername(UUID.randomUUID().toString());
        //设置为已删除管理员审核通过改为1
        user.setIsDelete(1);
        // @TODO插入数据库，用户表和律师表
        registerMapper.insertSelective(user);
        lawyersMapper.insertSelective(lawyerEntity);
        //@TODO 通知管理员审核
        return lawyerRegisterVO;
    }

    /**
     * 管理员注册接口业务
     * @param sysUser
     * @return
     */
    @Override
    public String adminRegister(SysUser sysUser) {
        //拿到当前登录用户的token
        String tokenValue = StpUtil.getTokenValue();
        //从token中获取当前登录用户的id
        Long loginId = StpUtil.getLoginIdAsLong();
        //根据id查询当前登录用户
        SysUser loginUser = registerMapper.selectOneById(loginId);
        //判断当前登录用户的权限
        if(!loginUser.getUserType().equals("ADMIN")){
            throw new InsufficientPermissionsException("当前用户没有权限");
        }
        //密码加密
        sysUser.setPassword(BCrypt.hashpw(sysUser.getPassword(), BCrypt.gensalt()));
        //设置用户类型为管理员
        sysUser.setUserType("ADMIN");
        //设置创建时间更新时间
        sysUser.setCreatedTime(new Date());
        sysUser.setUpdatedTime(new Date());
        //设置创建人更新人
        sysUser.setCreatedBy(loginUser.getUsername());
        sysUser.setUpdatedBy(loginUser.getUsername());
        //设置默认密码
        sysUser.setPassword(BCrypt.hashpw("@admin123456", BCrypt.gensalt()));
        //向数据库插入数据
        registerMapper.insertSelective(sysUser);
        return "添加管理员成功,管理员默认密码为@admin123456,请及时修改";
    }
}
